//---------------------------------------------------------------------
// File: DBExecuteNonQueryStep.cs
// 
// Summary: 
//---------------------------------------------------------------------

using System;
using System.Threading;
using System.Xml;
using BizUnit.Extensions.EntLib.Utilities;
using Microsoft.Services.BizTalkApplicationFramework.BizUnit;

namespace BizUnit.Extensions
{
    /// <summary>
	/// The EntLibDBExecuteNonQueryStep executes a non-query SQL statement. The number of rows affected is asserted if the 
    /// NumberOfRowsAffected element is specified
	/// </summary>
	/// 
	/// <remarks>
	/// The following shows an example of the Xml representation of this test step.
	/// 
	/// <code escaped="true">
	///	<TestStep assemblyPath="" typeName="Microsoft.Services.BizTalkApplicationFramework.BizUnit.DBExecuteNonQueryStep">
	///		<DelayBeforeExecution>1</DelayBeforeExecution>
    ///		<ConfigFileLocation>..\\..\\db.config</ConnectionString>
    ///		<DatabaseConfigName>Northwind</DatabaseConfigName>
	///		<NumberOfRowsAffected></NumberOfRowsAffected>
	///
	///		<!-- 
	///		The SQL Query to execute is built by formatting the RawSQLQuery substituting in the 
	///		SQLQueryParam's
	///		-->
	///		<SQLQuery>
	///			<RawSQLQuery>INSERT INTO TABLE (COLUMN1, COLUMN2) VALUES (VALUE1, {0},{1} )</RawSQLQuery>
	///			<SQLQueryParams>
	///				<SQLQueryParam takeFromCtx="Key1"></SQLQueryParam>
	///				<SQLQueryParam takeFromCtx="Key2"></SQLQueryParam>
	///			</SQLQueryParams>
	///		</SQLQuery>
	///	</TestStep>
	///	</code>
	///	
	///	<list type="table">
	///		<listheader>
	///			<term>Tag</term>
	///			<description>Description</description>
	///		</listheader>
	///		<item>
	///			<term>DelayBeforeExecution</term>
	///			<description>The number of seconds to wait before executing the step</description>
	///		</item>
	///		<item>
    ///			<term>ConfigFileLocation</term>
	///			<description>The config file containing the Enterprise Library configuration for db access</description>
	///		</item>
    ///     <item>
    ///			<term>DatabaseConfigName</term>
    ///			<description>The config section name of the databased used in the test</description>
    ///		</item>
    /// 
	///		<item>
	///			<term>NumberOfRowsAffected</term>
	///			<description>The number of rows affected. This is an optional element. If specified, it causes the test step to raise an exception when the number of rows affected
	///						by executing the non-query does not match the specified value</description>
	///		</item>
	///		<item>
	///			<term>SQLQuery/RawSQLQuery</term>
	///			<description>The raw SQL string that will be formatted by substituting in the SQLQueryParam</description>
	///		</item>
	///		<item>
	///			<term>SQLQuery/SQLQueryParams/SQLQueryParam</term>
	///			<description>The parameters to substitute into RawSQLQuery <para>(repeating)</para></description>
	///		</item>
	///	</list>
	///	</remarks>	
	public class EntLibDBExecuteNonQueryStep : ITestStep
	{
		/// <summary>
		/// ITestStep.Execute() implementation
		/// </summary>
		/// <param name='testConfig'>The Xml fragment containing the configuration for this test step</param>
		/// <param name='context'>The context for the test, this holds state that is passed beteen tests</param>
		public void Execute(XmlNode testConfig, Context context)
		{
			int delayBeforeCheck = context.ReadConfigAsInt32( testConfig, "DelayBeforeExecution" );
            string configFileLocation = context.ReadConfigAsString(testConfig, "ConfigFileLocation");
            string databaseConfigName = context.ReadConfigAsString(testConfig, "DatabaseConfigName");
		    XmlNode queryConfig = testConfig.SelectSingleNode( "SQLQuery" );
			int numberOfRowsAffected = testConfig.InnerXml.IndexOf("NumberOfRowsAffected",0,testConfig.InnerXml.Length) != -1? context.ReadConfigAsInt32 (testConfig, "NumberOfRowsAffected") : -1;
			string sqlQuery = EntLibDatabaseHelper.BuildSQLQuery( queryConfig, context );

            context.LogInfo("Using database connection string from config file: {0}", configFileLocation);
			context.LogInfo("Executing query: {0}", sqlQuery );

			// Sleep for delay seconds...
			Thread.Sleep(delayBeforeCheck*1000);

			int rowCount = EntLibDatabaseHelper.ExecuteNonQuery( configFileLocation, databaseConfigName, sqlQuery ) ;

            if (numberOfRowsAffected != -1)
            {
                if (rowCount != numberOfRowsAffected)
                    throw new Exception("Number of rows affected by the query does not match the value specified in the teststep. Number of rows affected was " + rowCount.ToString() + " and value specified was " + numberOfRowsAffected.ToString());
            }
            else
            {
                context.LogInfo("The number of rows affected by the query matched the value specified in the test step. " + rowCount.ToString() + "  rows were affected");
            }
		}
	}
}
